import OSS from 'ali-oss'
import { config } from './env'

// OSS配置接口
export interface OSSConfig {
  accessKeyId: string
  accessKeySecret: string
  bucket: string
  region: string
  endpoint?: string
  customDomain?: string
}

// 从环境配置获取OSS配置
const ossConfig: OSSConfig = {
  accessKeyId: config.oss.accessKeyId,
  accessKeySecret: config.oss.accessKeySecret,
  bucket: config.oss.bucket,
  region: config.oss.region,
  endpoint: config.oss.endpoint,
  customDomain: config.oss.customDomain
}

// 创建OSS客户端实例
export const ossClient = new OSS({
  accessKeyId: ossConfig.accessKeyId,
  accessKeySecret: ossConfig.accessKeySecret,
  bucket: ossConfig.bucket,
  region: ossConfig.region,
  endpoint: ossConfig.endpoint,
  secure: true, // 使用HTTPS
  timeout: 60000 // 60秒超时
})

// OSS操作工具类
export class OSSService {
  private client: OSS
  private bucket: string
  private customDomain?: string

  constructor() {
    this.client = ossClient
    this.bucket = ossConfig.bucket
    this.customDomain = ossConfig.customDomain
  }

  /**
   * 上传文件到OSS
   * @param fileName 文件名（包含路径）
   * @param fileBuffer 文件二进制数据
   * @param options 上传选项
   */
  async uploadFile(fileName: string, fileBuffer: Buffer, options?: any): Promise<OSS.PutObjectResult> {
    try {
      const result = await this.client.put(fileName, fileBuffer, {
        headers: {
          'Cache-Control': 'max-age=31536000', // 缓存1年
          'Content-Disposition': 'inline', // 浏览器内联显示
          ...options?.headers
        },
        ...options
      })
      return result
    } catch (error) {
      console.error('OSS上传失败:', error)
      throw new Error('文件上传失败')
    }
  }

  /**
   * 删除OSS文件
   * @param fileName 文件名
   */
  async deleteFile(fileName: string): Promise<void> {
    try {
      await this.client.delete(fileName)
    } catch (error) {
      console.error('OSS删除文件失败:', error)
      throw new Error('文件删除失败')
    }
  }

  /**
   * 获取文件访问URL
   * @param fileName 文件名
   * @param expireTime 过期时间（秒），默认1小时
   */
  getFileUrl(fileName: string, expireTime: number = 3600): string {
    try {
      if (this.customDomain) {
        // 如果配置了自定义域名，直接使用自定义域名
        return `${this.customDomain}/${fileName}`
      }
      
      // 使用OSS默认域名生成签名URL
      return this.client.signatureUrl(fileName, {
        expires: expireTime
      })
    } catch (error) {
      console.error('获取文件URL失败:', error)
      throw new Error('获取文件链接失败')
    }
  }

  /**
   * 生成头像文件名
   * @param userId 用户ID
   * @param fileExtension 文件扩展名
   */
  generateAvatarFileName(userId: number, fileExtension: string): string {
    const timestamp = Date.now()
    const randomStr = Math.random().toString(36).substring(7)
    return `avatars/${userId}/${timestamp}_${randomStr}.${fileExtension}`
  }

  /**
   * 验证文件类型
   * @param mimeType 文件MIME类型
   */
  validateImageType(mimeType: string): boolean {
    const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']
    return allowedTypes.includes(mimeType.toLowerCase())
  }

  /**
   * 验证文件大小
   * @param fileSize 文件大小（字节）
   * @param maxSizeMB 最大文件大小（MB），默认2MB
   */
  validateFileSize(fileSize: number, maxSizeMB: number = 2): boolean {
    const maxSizeBytes = maxSizeMB * 1024 * 1024
    return fileSize <= maxSizeBytes
  }
}

// 导出OSS服务实例
export const ossService = new OSSService()

// 验证OSS配置
export const validateOSSConfig = (): boolean => {
  return !!(
    ossConfig.accessKeyId &&
    ossConfig.accessKeySecret &&
    ossConfig.bucket &&
    ossConfig.region
  )
}

export default {
  ossClient,
  ossService,
  validateOSSConfig,
  OSSService
} 